<?php

namespace App\Service\System;

use App\Enums\OpenShop\MissionTemplateEnum;
use App\Enums\OpenShop\Notify\SystemNotifyCacheCode;
use App\Enums\WorkOrder\OrderEnum;
use App\Events\OpenShop\SystemNotifyCenterEvent;
use App\Http\Resources\SystemNotify\UserNotifyListResource;
use App\Jobs\SystemNotify\DelayPushJob;
use App\Models\Article\ArticleModel;
use App\Models\ChatGroup\ChatGroupHistoryModel;
use App\Models\ChatGroup\ChatGroupModel;
use App\Models\ChatGroup\ChatGroupUserModel;
use App\Models\Cruise\CruiseCheckAgainstModel;
use App\Models\Cruise\CruiseCheckRectifyModel;
use App\Models\Fee\FeeAnnualOrderModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\Shop\ShopModel;
use App\Models\Common\ConfigModel;
use App\Models\System\SystemNotifyCenterLogsModel;
use App\Models\System\SystemNotifyCenterModel;
use App\Models\System\SystemNotifyUserModel;
use App\Remote\Rms\RmsUserRemote;
use App\Remote\Rms\RmsUserRoleRemote;
use App\Service\BaseService;
use App\Service\ChatGroup\ChatGroupMessageReadService;
use App\Service\OpenShop\Feishu\MainProcessService;
use App\Service\Renew\RenewOrderService;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class SystemNotifyService extends BaseService
{
    /**
     * 配置列表
     *
     * @return array
     */
    public static function configTemp()
    {
        return [
            'type'         => SystemNotifyCenterModel::NOTIFY_TYPE_MAPPING_WEB_SHOW,
            'status'       => SystemNotifyCenterModel::NOTIFY_STATUS_MAPPING,
            'target'       => SystemNotifyCenterModel::NOTIFY_TARGET_MAPPING_WEB,
            'presenceArea' => SystemNotifyCenterModel::NOTIFY_PRESENCE_AREA_MAPPING,
            'pushType'     => SystemNotifyCenterModel::WEB_PUSH_TYPE_TEXT,
        ];
    }

    /**
     * 列表
     *
     * @param $pageNum
     * @param $pageSize
     * @param $type
     * @param $status
     * @return array
     */
    public static function list($pageNum, $pageSize, $where = [])
    {
        //where  'method' = SystemNotifyCenterModel::METHOD_TYPE_NOT_SET 过滤
        $paginator = SystemNotifyCenterModel::query()
                                            ->with("updatedUserRel")
                                            ->where('method', SystemNotifyCenterModel::METHOD_TYPE_MANUAL)
                                            ->when($where['id'], function ($query) use ($where) {
                                                $query->where('id', $where["id"]);
                                            })
                                            ->when($where['title'], function ($query) use ($where) {
                                                $query->where('title', 'like', '%' . $where['title'] . '%');
                                            })
                                            ->when($where['type'], function ($query) use ($where) {
                                                $query->where('type', $where['type']);
                                            })
                                            ->when($where['status'], function ($query) use ($where) {
                                                $query->where('status', $where['status']);
                                            })
                                            ->when($where['method'], function ($query) use ($where) {
                                                $query->where('method', $where['method']);
                                            })
                                            ->when($where['sendAtStart'] && $where['sendAtEnd'],
                                                function ($query) use ($where) {
                                                    $query->where('sendAt', '>', strtotime($where['sendAtStart']))
                                                          ->where('sendAt', '<', strtotime($where['sendAtEnd']));
                                                })
                                            ->where('isSystem', SystemNotifyCenterModel::NOTIFY_IS_SYSTEM_NO)
                                            ->orderByDesc('createdAt')
                                            ->paginate($pageSize, ['*'], 'pageNum', $pageNum);

        return [
            'list'     => collect($paginator->items())->map(
                function ($systemNotifyCenterModel) {
                    return [
                        "id"               => $systemNotifyCenterModel->id,
                        "title"            => $systemNotifyCenterModel->title,
                        "type"             => $systemNotifyCenterModel->type,
                        "shopId"           => $systemNotifyCenterModel->shopId,
                        "target"           => $systemNotifyCenterModel->target,
                        "targetId"         => $systemNotifyCenterModel->targetId,
                        "isSystem"         => $systemNotifyCenterModel->isSystem,
                        "smsTemplate"      => $systemNotifyCenterModel->smsTemplate,
                        "pushTitle"        => $systemNotifyCenterModel->pushTitle,
                        "url"              => $systemNotifyCenterModel->url,
                        "method"           => $systemNotifyCenterModel->method,
                        "summary"          => $systemNotifyCenterModel->summary,
                        "content"          => $systemNotifyCenterModel->content,
                        "autoRules"        => $systemNotifyCenterModel->autoRules,
                        "isPopup"          => $systemNotifyCenterModel->isPopup,
                        "presenceArea"     => $systemNotifyCenterModel->presenceArea,
                        "status"           => $systemNotifyCenterModel->status,
                        "sendAt"           => $systemNotifyCenterModel->sendAt,
                        "isOffPop"         => $systemNotifyCenterModel->isOffPop,
                        "popEffectiveDay"  => $systemNotifyCenterModel->popEffectiveDay,
                        "popEffectiveTime" => $systemNotifyCenterModel->popEffectiveTime ? formatDate($systemNotifyCenterModel->popEffectiveTime) : "",
                        "region"           => $systemNotifyCenterModel->region ? json_decode($systemNotifyCenterModel->region,
                            true) : "",
                        "createdAt"        => $systemNotifyCenterModel->createdAt->toDateTimeString(),
                        "updatedAt"        => $systemNotifyCenterModel->updatedAt->toDateTimeString(),
                        "updatedUsername"  => vsprintf("%s(%s)", [
                            attributeGet($systemNotifyCenterModel, "updatedUserRel.name", ""),
                            attributeGet($systemNotifyCenterModel, "updatedUserRel.nickname", ""),
                        ]),
                        "pushExtra"        => $systemNotifyCenterModel->pushExtra,
                        "pushType"         => $systemNotifyCenterModel->pushType,
                        "pushTargetId"     => $systemNotifyCenterModel->pushTargetId,
                        "notifyType"       => $systemNotifyCenterModel->notifyType,
                        "delayNotifyTime"  => $systemNotifyCenterModel->delayNotifyTime,
                    ];
                }
            ),
            'count'    => $paginator->total(),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
        ];
    }

    /**
     * 保存
     *
     * @param $id
     * @param $title
     * @param $type
     * @param $target
     * @param $smsTemplate
     * @param $pushTitle
     * @param $url
     * @param $method
     * @param $summary
     * @param $content
     * @param $isPopup
     * @param $presenceArea
     * @param int $shopId
     * @param array $pushExtra
     * @param int $isOffPop
     * @param int $popEffectiveDay
     * @param string $region
     * @return SystemNotifyCenterModel
     */
    public static function save(
        $id,
        $title,
        $type,
        $target,
        $smsTemplate,
        $pushTitle,
        $url,
        $method,
        $summary,
        $content,
        $isPopup,
        $presenceArea,
        int $shopId = 0,
        array $pushExtra = [],
        $isOffPop = 0,
        $popEffectiveDay = 7,
        $region = '',
        int $pushType = 0,
        int $pushTargetId = 0,
        int $popEffectiveTime = 0
    ): SystemNotifyCenterModel {
        if ($id) {
            $systemNoticeModel = SystemNotifyCenterModel::find($id);
        } else {
            $systemNoticeModel = new SystemNotifyCenterModel();
        }

        if (empty($pushType)) {
            if ($url) {
                $pushType = SystemNotifyCenterModel::PUSH_TYPE_2;
            } else {
                $pushType = SystemNotifyCenterModel::PUSH_TYPE_3;
            }

            switch ($pushType) {
                case SystemNotifyCenterModel::PUSH_TYPE_1:
                    $articleModel = ArticleModel::query()->where("id", $pushTargetId)->first();
                    $url          = $pushExtra["path"] = $systemNoticeModel->url = $systemNoticeModel->pushLocationUrl = vsprintf(
                        "kuafoodmerchantapp://operateArticleDetail?id=%d&type=%d",
                        [$articleModel->id, $articleModel->type]
                    );
                    break;
                default:
                    if (!empty($pushExtra["path"])) {
                        $systemNoticeModel->pushLocationUrl = $pushExtra["path"];
                    } else {
                        $pushExtra["path"] = $systemNoticeModel->pushLocationUrl = $url;
                    }
                    break;
            }
        } else {
            switch ($pushType) {
                case SystemNotifyCenterModel::PUSH_TYPE_1:
                    $articleModel = ArticleModel::query()->where("id", $pushTargetId)->first();
                    $url          = $pushExtra["path"] = $systemNoticeModel->url = $systemNoticeModel->pushLocationUrl = vsprintf(
                        "kuafoodmerchantapp://operateArticleDetail?id=%d&type=%d",
                        [$articleModel->id, $articleModel->type]
                    );
                    break;
                case SystemNotifyCenterModel::PUSH_TYPE_3:
                    $pushTargetId      = 0;
                    $pushExtra["path"] = $systemNoticeModel->pushLocationUrl = $url = "";
                    break;
                case SystemNotifyCenterModel::PUSH_TYPE_2:
                    $pushTargetId      = 0;
                    $pushExtra["path"] = $systemNoticeModel->pushLocationUrl = $url;
                    break;
            }
        }

        $systemNoticeModel->title        = $title;
        $systemNoticeModel->type         = $type;
        $systemNoticeModel->target       = $target;
        $systemNoticeModel->smsTemplate  = $smsTemplate;
        $systemNoticeModel->pushTitle    = $pushTitle;
        $systemNoticeModel->url          = $url;
        $systemNoticeModel->method       = $method;
        $systemNoticeModel->summary      = $summary;
        $systemNoticeModel->content      = $content;
        $systemNoticeModel->isPopup      = $isPopup;
        $systemNoticeModel->presenceArea = $presenceArea;
        $systemNoticeModel->shopId       = $shopId;

        $systemNoticeModel->isOffPop         = $isOffPop;//是否关闭弹窗
        $systemNoticeModel->popEffectiveDay  = $popEffectiveDay;//弹窗有效期天数-默认7天
        $systemNoticeModel->popEffectiveTime = $popEffectiveTime ?: (time() + $popEffectiveDay * 86400);//弹窗有效期时间
        $systemNoticeModel->region           = $region ? json_encode($region) : null;//分公司省市区域
        $systemNoticeModel->pushType         = $pushType;
        $systemNoticeModel->pushTargetId     = $pushTargetId;


        $systemNoticeModel->pushExtra = json_encode($pushExtra, JSON_UNESCAPED_UNICODE);
        $systemNoticeModel->save();

        return $systemNoticeModel;
    }

    /**
     * 记录日志
     */
    public static function recordLog($notifyModel, $title)
    {
        (new SystemNotifyCenterLogsModel([
            'notifyCenterId' => $notifyModel->id,
            'title'          => $title,
            'content'        => json_encode($notifyModel->toArray()),
            'createdByUid'   => getRmsUserId(),
            'createdBy'      => getRmsUserInfoByAuth()->username ?? '系统'
        ]))->addData();

    }

    /**
     * 开始推送
     *
     * @param $notifyId
     */
    public static function send($notifyId)
    {
        $systemNotifyModel = SystemNotifyCenterModel::find($notifyId);

        // 校验推送限制
        $pushLimit = self::checkPushTimeLimit($systemNotifyModel);
        if (!$pushLimit['code']) {
            BaseService::throwErr($pushLimit['msg']);
        }

        if ($systemNotifyModel->sendAt > 0) {
            return [];
        }

        event(new SystemNotifyCenterEvent($systemNotifyModel));

        $systemNotifyModel->sendAt = time();
        $systemNotifyModel->status = SystemNotifyCenterModel::NOTIFY_STATUS_2;
        $systemNotifyModel->save();

        // 写入日志
        SystemNotifyService::recordLog($systemNotifyModel, '推送消息');
    }

    /**
     * 校验推送时间，是否符合限制规则 true能推送 false不能
     * @return array
     */
    public static function checkPushTimeLimit(
        ?SystemNotifyCenterModel $systemNotifyCenterModel,
        int $pushTime = 0
    ): array {
        if (isTest()) {
            return BaseService::returnData(true);
        }

        if (!$systemNotifyCenterModel) {
            return BaseService::returnData(true);
        }

        // 仅限制所有人
        if ($systemNotifyCenterModel->target != SystemNotifyCenterModel::NOTIFY_TARGET_2) {
            return BaseService::returnData(true);
        }

        // 获取限制配置
        $limits = json_decode(ConfigModel::getValue('msgPush', 'pushTimeLimit'), true) ?? [];
        if (!$limits) {
            return BaseService::returnData(true);
        }

        if (!$pushTime) {
            $pushTime = time();
        }

        $t = date('H', $pushTime);

        foreach ($limits as $limit) {
            list($start, $end) = $limit;

            // 撞到限制时间了
            if ($t >= $start && $t < $end) {

                $msg = '';
                foreach ($limits as $v) {
                    $msg .= $v[0] . '-' . $v[1] . '点;';
                }
                $msg .= " 暂不允许推送全局消息";

                return BaseService::returnData(false, $msg);
            }
        }

        return BaseService::returnData(true);
    }

    /**
     * 消息延时推送
     *
     * @param object $params
     */
    public static function delayPush(object $params)
    {
        // 校验推送限制
        $pushLimit = self::checkPushTimeLimit(SystemNotifyCenterModel::query()->find($params->id),
            strtotime($params->delayNotifyTime));
        if (!$pushLimit['code']) {
            BaseService::throwErr($pushLimit['msg']);
        }

        SystemNotifyCenterModel::query()->where("id", $params->id)->update([
            "notifyType"      => SystemNotifyCenterModel::NOTIFY_TYPE_DELAY,
            "delayNotifyTime" => strtotime($params->delayNotifyTime)
        ]);

        dispatch((new DelayPushJob($params->id, strtotime($params->delayNotifyTime)))->onQueue('{system-notify-delay}'))
            ->delay(strtotime($params->delayNotifyTime) - time());
    }

    /**
     * 消息延时推送
     *
     * @param object $params
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public static function cancelDelayPush(object $params)
    {
        SystemNotifyCenterModel::query()->where("id", $params->id)->update([
            "notifyType"      => SystemNotifyCenterModel::NOTIFY_TYPE_DIRECT,
            "delayNotifyTime" => 0,
            "updatedByUid"    => getRmsUserId()
        ]);
    }

    /**
     * 关闭推送
     *
     * @param $notifyId
     */
    public static function close($notifyId)
    {
        $systemNotifyModel         = SystemNotifyCenterModel::find($notifyId);
        $systemNotifyModel->status = SystemNotifyCenterModel::NOTIFY_STATUS_4;
        $systemNotifyModel->save();

//        SystemNotifyUserModel::query()->where('notifyCenterId', $notifyId)->delete();

        // 关闭消息推送, 发送记录未删除
        // 写入日志
        SystemNotifyService::recordLog($systemNotifyModel, '关闭了消息推送, 发送记录未删除');

        $userList = SystemNotifyUserModel::query()
                                         ->select(['userId'])
                                         ->where('notifyCenterId', $notifyId)
                                         ->get()
                                         ->pluck('userId')
                                         ->unique()
                                         ->toArray();

        Redis::pipeline(function ($pipe) use ($userList, $systemNotifyModel) {
            foreach ($userList as $userId) {
                $unreadNumKey = SystemNotifyCacheCode::getUserUnreadListKey($userId, $systemNotifyModel->type);
//                $pipe->LREM($unreadNumKey, 0, $systemNotifyModel->id);
                $pipe->LREM($unreadNumKey, $systemNotifyModel->id, 0);
            }
        });
    }

    /**
     * @param $notifyId
     * @param array $preTargetList
     * @return array|void
     */
    public static function preSend($notifyId, array $preTargetList)
    {
        if (empty($preTargetList)) {
            return [];
        }
        $systemNotifyModel = SystemNotifyCenterModel::find($notifyId);

        event(new SystemNotifyCenterEvent($systemNotifyModel, $preTargetList));

        // 写入日志
        SystemNotifyService::recordLog($systemNotifyModel, '预推送消息');
    }

    public static function getTargetUserList(Model $systemNotifyModel)
    {
        $userList = [];
        switch ($systemNotifyModel->target) {
            case SystemNotifyCenterModel::NOTIFY_TARGET_1:
            case SystemNotifyCenterModel::NOTIFY_TARGET_2:
                $region = collect(json_decode($systemNotifyModel->region, true));
                if ($region->first() == 'ALL') {
                    $cityCode = 'ALL';
                } else {
                    $cityCode = $region->pluck('2')->implode(',');
                }
                $lastId = 0;
                do {
                    $list = RmsUserRemote::getNotifyAllUserList($lastId, $systemNotifyModel->target, $cityCode);
                    if (empty($list)) {
                        break;
                    }
                    $lastId  = end($list);
                    $listArr = [];
                    foreach ($list as $value) {
                        $listArr[] = [
                            'id' => $value
                        ];
                    }
                    $userList = array_merge($userList, $listArr);
                } while (true);


                break;
            case SystemNotifyCenterModel::NOTIFY_TARGET_3:
                $userList = [
                    [
                        'id' => $systemNotifyModel->targetId
                    ]
                ];
        }
        return $userList;
    }

    /**
     * 获取第一个弹窗详情
     *
     * @param int $userId
     * @param int $presenceArea
     * @return Builder|Model|object|null
     */
    public static function getUserPopListFirst(int $userId, int $presenceArea)
    {
        $allPopListKey = SystemNotifyCacheCode::getUserNotifyPopListKey($userId);

        $allPopListIds = Redis::Lrange($allPopListKey, 0, 100);

        $notifyInfo = SystemNotifyCenterModel::query()
                                             ->whereIn('id', $allPopListIds)
                                             ->where('presenceArea', 'like', '%' . $presenceArea . '%')
                                             ->first();

        return $notifyInfo;
    }

    /**
     * 获取第一个弹窗详情
     *
     * @param int $userId
     * @return Builder[]|Collection
     */
    public static function getUserPopList(int $userId)
    {
        $allPopListKey = SystemNotifyCacheCode::getUserNotifyPopListKey($userId);
        $allPopListIds = Redis::Lrange($allPopListKey, 0, 100);
        $unsetList     = [];
        $list          = SystemNotifyCenterModel::query()
                                                ->whereIn('id', $allPopListIds)
                                                ->where(function ($query) {
                                                    return $query->where("type", "<>",
                                                        SystemNotifyCenterModel::NOTIFY_TYPE_5)->orWhere(function (
                                                        $query
                                                    ) {
                                                        return $query->where("type",
                                                            SystemNotifyCenterModel::NOTIFY_TYPE_5)
                                                                     ->where("shopId",
                                                                         request()->headers->get("shopId", 0))
                                                                     ->where("shopId", ">", 0);
                                                    });
                                                })
                                                ->with('notifyUserOneRel', function ($query) use ($userId) {
                                                    return $query->where('readAt', 0)->where('userId', $userId);
                                                })
                                                ->where('status', '!=', SystemNotifyCenterModel::NOTIFY_STATUS_4)
                                                ->get()
                                                ->filter(function ($value) use (&$unsetList) {
                                                    if (empty($value->notifyUserOneRel->createdAt->timestamp)) {
                                                        return false;
                                                    }
                                                    if ($value->popEffectiveTime != 0 && time() > $value->popEffectiveTime) {
                                                        $unsetList[] = $value->id;
                                                        return false;
                                                    } else {
                                                        return true;
                                                    }
                                                })
                                                ->each(function ($value) {
                                                    if (empty($value->url)) {
                                                        $userNotifyId = $value->notifyUserOneRel->id ?? 0;
                                                        $value->url   = config('webUrl.notify_web_cdn_url') . '#/pages/message-center/detail/index?id=' . $userNotifyId . '&time=' . time();
                                                    }
                                                    unset($value->notifyUserOneRel);
                                                })
                                                ->values();

        if (!empty($unsetList)) {
            foreach ($unsetList as $value) {
                self::removePopListKey($userId, $value);
            }
        }
        return $list;
    }

    /**
     * 消息一级页面列表
     *
     * @param int $userId
     * @param int $shopId
     * @return array
     */
    public static function getUserNotifyList(int $userId, int $shopId)
    {
        /*$queryIds = [];
        foreach (SystemNotifyCenterModel::NOTIFY_TYPE_MAPPING as $key => $value) {
            $listKey = SystemNotifyCacheCode::getUserNotifyListKey($userId, $key);

            $allPopListIds  = Redis::Lrange($listKey, 0, 1);
            $queryIds[$key] = array_shift($allPopListIds);
        }

        $notifyInfo = SystemNotifyCenterModel::query()
                                             ->whereIn('id', array_filter($queryIds))
                                             ->get()
                                             ->keyBy('id')
                                             ->toArray();

        $timeList = [];
        SystemNotifyUserModel::query()
                             ->whereIn('notifyCenterId', array_filter($queryIds))
                             ->where('userId', $userId)
                             ->get()
                             ->each(function ($value) use (&$timeList) {
                                 $timeList[$value->notifyCenterType] = [
                                     'id'        => $value->id,
                                     'createdAt' => date('Y-m-d H:i:s', $value->createdAt->timestamp)
                                 ];
                             });*/

        $result = [];
        foreach (SystemNotifyCenterModel::NOTIFY_TYPE_MAPPING as $key => $value) {
            // 只展示一个月内的
            $systemNotifyUserModel = SystemNotifyUserModel::query()
                                                          ->with([
                                                              'notifyCenterRel' => function ($query) {
                                                                  $query->where('status', '!=',
                                                                      SystemNotifyCenterModel::NOTIFY_STATUS_4);
                                                              }
                                                          ])
                                                          ->where('userId', $userId)
                                                          ->where('notifyCenterType', $key)
                                                          ->orderByDesc('createdAt')
                                                          ->where('createdAt', '>', Carbon::now()->subMonth())
                                                          ->first();

            $result[$key] = [
                'type'             => $key,
                'title'            => $value,
                'contentTitle'     => $systemNotifyUserModel->notifyCenterRel->title ?? '暂无消息',
                'contentCreatedAt' => $systemNotifyUserModel && $systemNotifyUserModel->createdAt ? formatDate(strtotime($systemNotifyUserModel->createdAt)) : '',
                'icon'             => SystemNotifyCenterModel::NOTIFY_TYPE_ICON_MAPPING[$key],
                'unReadNum'        => (int)Redis::LLEN(SystemNotifyCacheCode::getUserUnreadListKey($userId, $key))
            ];
        }
        $result = array_values($result);

        // 判断客服群权限
        $group = ChatGroupUserModel::checkAppUserIn($shopId, $userId, ChatGroupModel::TYPE_CUSTOMER_SERVE);
        if ($group) {

            // 最后一条会话消息
            $history = ChatGroupHistoryModel::query()
                                            ->where('groupId', $group->id)
                                            ->where('recall', 0)
                                            ->where('sensitive', 0)
                                            ->orderByDesc('id')
                                            ->first();

            $arr = [
                'type'             => SystemNotifyCenterModel::NOTIFY_TYPE_6,
                'title'            => $group->name,
                'contentTitle'     => $history ? $history->getText() : '',
                'contentCreatedAt' => $history ? $history->createdAt->toDateTimeString() : '',
                'icon'             => SystemNotifyCenterModel::NOTIFY_TYPE_ICON_MAPPING[SystemNotifyCenterModel::NOTIFY_TYPE_6],
                'unReadNum'        => (new ChatGroupMessageReadService($userId))->getUnreadNums($group->id),
                'bizId'            => $group->id,
            ];

            array_unshift($result, $arr);
        }

        return $result;
    }

    /**
     * 消息二级页面列表
     *
     * @param int $userId
     * @return array
     */
    public static function getUserNotifyListByType(int $pageSize, int $pageNum, int $userId, int $type)
    {
        $result = [];
        $list   = SystemNotifyUserModel::query()
                                       ->where('userId', $userId)
                                       ->where('notifyCenterType', $type)
                                       ->with('notifyCenterRel')
                                       ->orderBy('createdAt', 'desc')
                                       ->paginate($pageSize, ['*'], 'pageNum', $pageNum);


        collect($list->items())->each(function ($value) use (&$result) {
            if (null === $value->notifyCenterRel) {
                return;
            }
            if ($value->notifyCenterRel->status == SystemNotifyCenterModel::NOTIFY_STATUS_4) {
                return;
            }

            $result[] = [
                'id'             => (string)$value->id,
                'notifyCenterId' => $value->notifyCenterId,
                'url'            => $value->notifyCenterRel->url,
                'title'          => $value->notifyCenterRel->title,
                'summary'        => $value->notifyCenterRel->summary,
                'pushType'       => $value->notifyCenterRel->pushType,
                'pushTargetId'   => $value->notifyCenterRel->pushTargetId,
                'readAt'         => $value->readAt,
                'isContent'      => empty(self::clearHtmlLabel($value->notifyCenterRel->content)) ? 0 : 1,
//                'content'        => self::clearHtmlLabel($value->notifyCenterRel->content),
                'createdAt'      => date('Y-m-d H:i:s', $value->createdAt->timestamp),
            ];
        });

        return [
            'list'     => $result,
            'count'    => $list->total(),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
        ];
    }

    /**
     * 获取消息详情
     *
     * @param int $userId
     * @param int $type
     * @param int $notifyId
     * @return array
     */
    public static function getNotifyInfoById(int $userId, int $id)
    {
        $value = SystemNotifyUserModel::query()
                                      ->where('userId', $userId)
                                      ->where('id', $id)
                                      ->with('notifyCenterRel')
                                      ->first();

        if (null == $value) {
            return [];
        }

        $result = [
            'id'             => $value->id,
            'notifyCenterId' => $value->notifyCenterId,
            'url'            => $value->url,
            'title'          => $value->notifyCenterRel->title,
            'summary'        => $value->notifyCenterRel->summary,
            'content'        => $value->notifyCenterRel->content,
            'createdAt'      => date('Y-m-d H:i:s', $value->createdAt->timestamp),
        ];

        return $result;
    }

    public static function clearHtmlLabel($str)
    {
        $str = str_replace('<p>', '', $str);
        $str = str_replace('</p>', '', $str);
        $str = str_replace('<br>', '', $str);

        return $str;
    }

    /**
     * 已读消息
     *
     * @param int $userId
     * @param int $notifyCenterId
     * @param int $notifyUserId
     */
    public static function readNotify(int $userId, int $notifyCenterId, int $notifyUserId = 0)
    {

        try {


            if (!empty($notifyUserId)) {
                $notifyUserModel = SystemNotifyUserModel::query()
                                                        ->where('id', $notifyUserId)
                                                        ->where('userId', $userId)
                                                        ->first();
                $notifyCenterId  = $notifyUserModel->notifyCenterId ?? 0;
            }

            $notifyModel = SystemNotifyCenterModel::query()
                                                  ->where('id', $notifyCenterId)
                                                  ->first();

            if (empty($notifyModel)) {
                return;
            }

            // 用户-储存弹窗数据 - 1
            self::removePopListKey($userId, $notifyCenterId);

            // 用户-未读消息 - 1
            $unreadNumKey = SystemNotifyCacheCode::getUserUnreadListKey($userId, $notifyModel->type);
            Redis::LREM($unreadNumKey, 0, $notifyCenterId);
            // 写入记录
            SystemNotifyUserModel::query()->where([
                'notifyCenterId' => $notifyCenterId,
                'userId'         => $userId,
            ])->update(
                [
                    'readAt' => time()
                ]
            );
        } catch (\Exception $exception) {
            Log::error('readNotify', [
                'errorMsg' => $exception->getMessage(),
                'line'     => $exception->getLine()
            ]);
        }
    }

    public static function removePopListKey($userId, $notifyCenterId)
    {
        $popKey = SystemNotifyCacheCode::getUserNotifyPopListKey($userId);
        Redis::LREM($popKey, 0, $notifyCenterId);
    }

    /**
     * 已读所有消息
     *
     * @param int $userId
     * @param int $notifyId
     */
    public static function readAllNotify(int $userId)
    {
        Redis::DEL(SystemNotifyCacheCode::getUserNotifyPopListKey($userId));
        foreach (SystemNotifyCenterModel::NOTIFY_TYPE_MAPPING as $key => $value) {
            $key = SystemNotifyCacheCode::getUserUnreadListKey($userId, $key);
            Redis::DEL($key);
        }
        // 写入记录
        SystemNotifyUserModel::query()->where(
            [
                'userId' => $userId,
            ]
        )->update(['readAt' => time()]);
    }

    /**
     * 统计数据
     *
     * @param int $userId
     * @param int $notifyId
     */
    public static function statistical(int $pageNum, int $pageSize, int $id, int $type)
    {
        $notifyModel = SystemNotifyCenterModel::find($id);


        $notifyUserList = SystemNotifyUserModel::query()
                                               ->where('notifyCenterId', $id)
                                               ->when($type == 2, function ($query) {
                                                   $query->where('readAt', '>', 0);
                                               })
                                               ->when($type == 3, function ($query) {
                                                   $query->where('readAt', 0);
                                               })
                                               ->paginate($pageSize, ['*'], 'pageNum', $pageNum);


        $queryUserList = collect($notifyUserList->items())->pluck('userId')->toArray();


        $userList = count($queryUserList) > 0 ? RmsUserRemote::getRmsUserByIds($queryUserList) : [];
        $userList = array_column($userList, null, 'id');

        $returnList = [];
        foreach ($notifyUserList->items() as $item) {


            $userId       = $item->userId;
            $returnList[] = [
                'id'             => $item->id,
                'notifyCenterId' => $notifyModel->id,
                'mobile'         => $userList[$userId]['mobile'] ?? '未知用户' . $userId,
                'username'       => $userList[$userId]['username'] ?? '未知用户' . $userId,
                'shopName'       => '无',
                'sendAt'         => date('Y-m-d H:i:s', $item->createdAt->timestamp),
                'readAt'         => empty($item->readAt) ? '' : date('Y-m-d H:i:s', $item->readAt)
            ];
        }

        return [
            'list'     => $returnList,
            'count'    => $notifyUserList->total(),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize,
        ];

    }

    /**
     * 未读 总数量
     *
     * @param int $userId
     * @param int $shopId
     * @return array
     * @throws GuzzleException
     */
    public static function getUnreadNum(int $userId, int $shopId): array
    {
        $userNotify = SystemNotifyUserModel::query()
                                           ->whereHas("notifyCenterRel", function ($query) {
                                               $query->where("status", "<>", SystemNotifyCenterModel::NOTIFY_STATUS_4);
                                           })
                                           ->with('notifyCenterRel')
                                           ->where('userId', $userId)
                                           ->where("createdAt", ">=", Carbon::now()->subDays(7)->timestamp)
                                           ->limit(20)
                                           ->orderByDesc("id")
                                           ->get();

        return [
            'total'      => SystemNotifyUserModel::query()->where('userId', $userId)->where('readAt', 0)->count(),
            'userNotify' => [
                "total" => $userNotify->count(),
                "list"  => UserNotifyListResource::collection($userNotify)
            ],
            'taskTotal'  => self::getTaskBoard($userId, $shopId)["total"],
            'popList'    => SystemNotifyService::getUserPopList($userId)
        ];
    }

    /**
     * 自定义批量推送
     *
     * @param array $userIds
     * @param string $title
     * @param string $summary
     * @param string $url
     * @param int $shopId
     * @param int $type
     * @param int $target
     * @param string $smsTemplate
     * @param int $method
     * @param string $content
     * @param int $isPop
     * @param int $popArea
     * @param string $logTitle
     * @param array $pushExtra 文档：https://onepiece-group.feishu.cn/wiki/wikcn5I4jIGyO8NOImw5wvFRLxb
     */
    public static function customerBatchPush(
        array $userIds,
        string $title,
        string $summary,
        string $url,
        int $shopId = 0,
        int $type = SystemNotifyCenterModel::NOTIFY_TYPE_3,
        int $target = SystemNotifyCenterModel::NOTIFY_TARGET_1,
        string $smsTemplate = "",
        int $method = SystemNotifyCenterModel::METHOD_TYPE_AUTOMATIC,
        string $content = "",
        int $isPop = SystemNotifyCenterModel::IS_POPUP_ON,
        int $popArea = 1,
        string $logTitle = "创建消息",
        array $pushExtra = []
    ) {
        if (empty($content) && empty($url)) {
            $content = $summary;
        }
        $notify = SystemNotifyService::save(
            false,
            $title,
            $type,
            $target,
            $smsTemplate,
            $title,
            $url,
            $method,
            $summary,
            $content,
            $isPop,
            $popArea,
            $shopId,
            $pushExtra
        );
        SystemNotifyService::recordLog($notify, $logTitle);
        SystemNotifyService::preSend($notify->id, $userIds);
    }

    /**
     * 获取消息中心任务看板
     *
     * @param int $uid
     * @param int $shopId
     * @return array
     * @throws GuzzleException
     */
    public static function getTaskBoard(int $uid, int $shopId): array
    {
        //todo 判断是否为店长 || 演示角色
        $userShopRole     = RmsUserRoleRemote::getUserRoleByUserId([$uid], RmsUserRoleRemote::ROLE_BUSINESS_TYPE,
            $shopId);
        $shopMerchantRole = attributeGet($userShopRole, "userRole.0.userRole", []);
        $roleShow         = false;
        if (
            in_array(config('rms.role.merchant.shopManagerId'), $shopMerchantRole)//店长
            ||
            in_array(config('rms.role.merchant.demonstrationId'), $shopMerchantRole)//演示
        ) {
            $roleShow = true;
        }

        // ToDo 判断登录方式
        $loginType = attributeGet(request(), "loginType", "");

        $taskBoard = [];
        $mDomain   = config('open-shop.m');
        $shopModel = ShopModel::query()->where("id", $shopId)->first();


        if ($loginType == "fs" || $roleShow) {
            // todo 年费订单未支付完成
            $unpaidCompletionList = FeeAnnualOrderModel::unpaidCompletionList($shopId);
            if ($unpaidCompletionList->count()) {
                $unpaidCompletionList->each(function ($unpaidCompletion) use (
                    &$taskBoard,
                    $mDomain,
                    $shopId,
                    $shopModel
                ) {
                    array_push($taskBoard, [
                        "title"   => '您有1笔年管理费订单信息，请点击立即处理',
                        "content" => vsprintf("您的门店夸父炸串（%s），年管理费订单已生成，到期时间%s ，请点击「立即处理」完成确认。",
                            [
                                $shopModel->name,
                                Carbon::createFromTimestamp($unpaidCompletion->endTime)->format("Y-m-d")
                            ]),
                        "type"    => 1,
                        "url"     => vsprintf(
                            "%s?url=%s", [
                                "kuafoodmerchantapp://webView",
                                urlencode($mDomain . "order/sign/{$unpaidCompletion->feeOrderNo}/annualFee/{$shopId}?t=" . time())
                            ]
                        )
                    ]);
                });
            }

            // todo  筹备中
            if ($unpaidCompletionList->isEmpty()) {
                $prepareStatus = ShopModel::shopInPrepare($shopId);
                if ($prepareStatus) {
                    array_push($taskBoard, [
                        "title"   => '您有1笔筹备中的开店订单，请点击查看详情',
                        "content" => "您的门店{$shopModel->name}，开店阶段筹备中，请点击「立即处理」完成确认。",
                        "type"    => 4,
                        "url"     => "kuafoodmerchantapp://openSchedule"
                    ]);
                }
            }

            // todo 违约函 || 整改单
            $cruiseCheckAgainstModel = (new CruiseCheckAgainstModel())->getWaitAgainstIds([$shopId]);
            if (isset($cruiseCheckAgainstModel[$shopId]) && count($cruiseCheckAgainstModel[$shopId]) > 0) {
                // todo 违约函
                collect($cruiseCheckAgainstModel[$shopId])->where("level", "<>", 1)->each(function ($cruiseCheckAgainst
                ) use (
                    &$taskBoard,
                    $mDomain,
                    $shopModel
                ) {
                    array_push($taskBoard, [
                        "title"   => '您有1条违约信息，请点击立即处理',
                        "content" => "您的门店夸父炸串（{$shopModel->name}），违约函已下发，请点击「立即处理」完成确认。",
                        "type"    => 2,
                        "url"     => vsprintf("%s?url=%s", [
                            "kuafoodmerchantapp://webView",
                            urlencode("{$mDomain}audit/pay-fine?againstId={$cruiseCheckAgainst["id"]}")
                        ])
                    ]);
                });

                // todo 整改单
                collect($cruiseCheckAgainstModel[$shopId])->where("level", 1)->each(function ($cruiseCheckAgainst) use (
                    &$taskBoard,
                    $mDomain,
                    $shopModel
                ) {
                    array_push($taskBoard, [
                        "title"   => '您有1条整改信息，请点击立即处理',
                        "content" => "您的门店夸父炸串（{$shopModel->name}），整改单已下发，限期整改完成，请点击「立即处理」完成确认。",
                        "type"    => 3,
                        "url"     => vsprintf("%s?url=%s", [
                            "kuafoodmerchantapp://webView",
                            urlencode(config('webUrl.notify_web_cdn_url') . "?t=" . time() . "#/pages/audit/report/break-contract?againstId={$cruiseCheckAgainst['id']}")
                        ])
                    ]);
                });
            }


            // ToDo 门店续签
            $renewOrders = RenewOrderService::getRenewOrdersByShopIds([$shopId]);
            if ($nowRenewOrder = (collect($renewOrders))->where("shopId", $shopId)->first()) {
                array_push($taskBoard, [
                    "title"   => "您有1条门店续签信息，请点击立即处理",
                    "content" => "您的门店夸父炸串（{$shopModel->name}），续签办理未完成，请点击「立即处理」完成确认。",
                    "type"    => 5,
                    "url"     => attributeGet($nowRenewOrder, "linkUrl", "")
                ]);
            }


            // todo 整改单
            $rectifyAuditShop = CruiseCheckRectifyModel::getRectificationList($shopId);
            if ($rectifyAuditShop->isNotEmpty()) {
                array_push($taskBoard, [
                    "title"   => "您有{$rectifyAuditShop->count()}条整改信息，请点击立即处理",
                    "content" => "您的门店夸父炸串（{$shopModel->name}），整改单已下发，限期整改完成，请点击「立即处理」完成确认。",
                    "type"    => 6,
                    "url"     => vsprintf("%s?url=%s", [
                        "kuafoodmerchantapp://webView",
                        urlencode(config('webUrl.notify_web_cdn_url') . "#pages/audit/rectify/list?status=0")
                    ])
                ]);
            }
        }

        return [
            "total" => count($taskBoard),
            "list"  => $taskBoard
        ];
    }
}
